package evaluator

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"lark/src/exception"
	"lark/src/lexer"
	"lark/src/object"
	"lark/src/parser"
	"lark/src/utils"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"github.com/atotto/clipboard"
	_ "github.com/go-sql-driver/mysql"
	"golang.org/x/sys/windows/registry"
)

var builtins = map[string]*object.Builtin{
	//输入
	"input": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 1 {
				fmt.Print(args[0].Inspect())
			}
			var userInput string

			// 这个函数会暂停程序执行，直到用户输入内容并按回车键
			fmt.Scanln(&userInput)

			return &object.String{Value: userInput}
		},
	},
	//打印输出,第二个参数换行
	"print": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			for index, _ := range args {
				switch arg := args[index].(type) {
				case *object.Integer:
					fmt.Println(arg.Value)
				case *object.Float:
					fmt.Println(arg.Value)
				case *object.String:
					fmt.Println(arg.Value)
				case *object.Identifier:
					fmt.Println(arg.Value)
				case *object.Boolean:
					fmt.Println(arg.Value)
				case *object.ReturnValue:
					fmt.Println(arg.Inspect())
				case *object.Function:
					fmt.Println(arg.Inspect())
				case *object.Array:
					fmt.Println(arg.Inspect())
				case *object.Hash:
					fmt.Println(arg.Inspect())
				case *object.Date:
					fmt.Println(arg.Inspect())
					// utils.SaveLog(arg.Value)
				case *object.HttpResponse:
					fmt.Println(arg.Inspect())
				default:

					exception.Evaluator(0, 0, "不支持对\"print\"的论点，得到 %s", args[0].Type())

				}
			}
			return &object.Boolean{Value: true}
		},
	},
	//打印输出不换行
	"println": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			for index, _ := range args {
				switch arg := args[index].(type) {
				case *object.Integer:
					fmt.Println(arg.Value)
				case *object.Float:
					fmt.Println(arg.Value)
				case *object.String:
					fmt.Println(arg.Value)
				case *object.Identifier:
					fmt.Println(arg.Value)
				case *object.Boolean:
					fmt.Println(arg.Value)
				case *object.ReturnValue:
					fmt.Println(arg.Value)
				case *object.Array:
					fmt.Println(arg.Inspect())
				case *object.Hash:
					fmt.Println(arg.Inspect())
				case *object.Date:
					fmt.Println(arg.Inspect())
					// utils.SaveLog(arg.Value)
				case *object.HttpResponse:
					fmt.Println(arg.Inspect())
				default:

					exception.Evaluator(0, 0, "不支持对\"println\"的论点，得到 %s", args[0].Type())

				}
			}
			// return NULL
			return &object.Boolean{Value: true}
		},
	},
	//检查一个变量是否为空
	"empty": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			switch arg := args[0].(type) {
			case *object.Integer:
				if arg.Value > 0 {
					return &object.Empty{Value: true}
				}
				return &object.Empty{Value: false}
			case *object.Float:
				if arg.Value > 0 {
					return &object.Empty{Value: true}
				}
				return &object.Empty{Value: false}
			case *object.String:
				if arg.Inspect() != "" {
					return &object.Empty{Value: true}
				}
				return &object.Empty{Value: false}
			case *object.Boolean:
				return &object.Empty{Value: arg.Value}
			case *object.Array:
				if len(arg.Elements) > 0 {
					return &object.Empty{Value: true}
				}
				return &object.Empty{Value: false}
			default:
				exception.Evaluator(0, 0, "不支持对\"empty\"的论点，得到 %s", args[0].Type())
			}
			return &object.Empty{Value: false}
		},
		/* Fns: func(args ...object.Object) object.Object {

			fmt.Println("empty()")
			return &object.Boolean{Value: true}
		}, */
		// Fields: make(map[string]object.BuiltinFunction),
		/* Fields: map[string]object.BuiltinFunction{
			// 获取时间戳
			"time": func(args ...object.Object) object.Object {
				// 获取当前时间
				now := time.Now()
				// 获取时间戳（秒）
				timestamp := now.Unix()
				fmt.Println(timestamp)
				return &object.Integer{Value: timestamp}
			},
		}, */
	},
	/*
		* 获取日期时间(y-m-d h:i:s)
		Y 四位数的年份表示（000-9999） y 两位数的年份表示（00-99）
		m 月份（01-12）
		d 月内中的一天（0-31）

		H 24小时制小时数（0-23） h 12小时制小时数（01-12）
		i 分钟数（00=59）
		s 秒（00-59）
	*/
	"date": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) > 0 {
				arg := args[0]
				/* fmt.Printf("%#v\n", arg)
				fmt.Printf("%T", arg) */
				dateTime := time.Now() // 格式化当前时间
				var formattedTime string
				if arg.Inspect() != "" {
					/*
					 * 24小时制小时数（0-23）dateTime.Format("15:04:05")
					 * 12小时制小时数（01-12）dateTime.Format("03:04:05 PM")
					 */
					dateMap := map[string]string{"Y-m-d H:i:s": dateTime.Format("2006-01-02 15:04:05"),
						"y-m-d H:i:s": dateTime.Format("06-01-02 15:04:05"),
						"Y-m-d":       dateTime.Format("2006-01-02"),
						"y-m-d":       dateTime.Format("06-01-02"),
						"Y":           dateTime.Format("2006"),
						"y":           dateTime.Format("06"), "m": dateTime.Format("01"), "d": dateTime.Format("02"),
						"H:i:s": dateTime.Format("15:04:05"), "h:i:s": dateTime.Format("15:04:05 PM"), "H": dateTime.Format("15"), "h": dateTime.Format("15 PM"), "i": dateTime.Format("04"), "s": dateTime.Format("05")}
					formattedTime, ok := dateMap[arg.Inspect()]
					if !ok || formattedTime == "" {
						return exception.Evaluator(0, 0, "date中的参数错误 %s", args[0].Type())
					}

				} else {
					formattedTime = dateTime.Format("2006-01-02 15:04:05")
				}
				return &object.Date{Value: formattedTime}
			} else {
				dateTime := time.Now() // 格式化当前时间
				formattedTime := dateTime.Format("2006-01-02 15:04:05")
				return &object.Date{Value: formattedTime}
			}
		},
	},
	// 获取时间戳
	"time": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			// 获取当前时间
			now := time.Now()
			// 获取时间戳（秒）
			timestamp := now.Unix()
			return &object.Integer{Value: timestamp}
		},
		Fields: map[string]object.BuiltinFunction{
			// 获取时间戳
			"ti": func(args ...object.Object) object.Object {
				// 获取当前时间
				now := time.Now()
				// 获取时间戳（秒）
				timestamp := now.Unix()
				fmt.Println(timestamp)
				return &object.Integer{Value: timestamp}
			},
		},
	},
	/*
		* 发起网络请求
		url: 必需，开发者服务器接口地址
		method: 可选，文件打开模式
		data: 请求的参数
		header: 设置请求的 header
	*/
	"request_": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			params := args[0].(*object.Hash).Pairs

			var linkUrl string
			// method：一个字符串，表示 HTTP 请求的方法（如 "GET", "POST", "PUT", "DELETE" 等）
			var method string
			var data string
			// var header string

			for key, value := range params {

				if key.Value == 0x4c4e8b193dc8be7e {
					linkUrl = value.Value.Inspect()
				}
				if key.Value == 0x230c05e5fb0433b0 {
					method = value.Value.Inspect()
				}
				if key.Value == 9609368131611085317 {
					data = value.Value.Inspect()
				}
				if key.Value == 4201977977006070112 {
					fmt.Println(value.Value)
					fmt.Println(value.Value.Inspect())
					// header = value.Value.Inspect()
				}

			}

			env := object.NewEnvironment()

			// 创建一个HTTP客户端
			client := &http.Client{}

			// 定义一个结构体来存储请求和错误
			type HttpResult struct {
				Request *http.Request
				Error   error
			}

			// 调用 http.NewRequest 并将结果存储在 HttpResult 结构体中
			result := HttpResult{
				Request: nil, // 初始化为 nil，稍后将通过函数赋值
				Error:   nil, // 同样初始化为 nil
			}
			if method == "get" || method == "delete" || method == "head" {
				// 使用http.NewRequest创建一个GET,DELETE,HEAD请求
				result.Request, result.Error = http.NewRequest(strings.ToUpper(method), linkUrl, nil)
			} else {
				//method转为大写，post,put等
				result.Request, result.Error = http.NewRequest(strings.ToUpper(method), linkUrl, bytes.NewBuffer([]byte(data)))
			}
			if result.Error != nil {
				fmt.Println("创建请求失败:", result.Error)
			}

			// 设置自定义的请求头
			// req.Header.Set("Content-Type", "charset=utf-8")
			// req.Header.Set("Accept-Charset", "utf-8")
			result.Request.Header.Add("Accept-Charset", "utf-8")

			result.Request.Header.Set("Content-Type", "application/json")

			// req.Header.Set("accept", "application/vnd.emall.v2+json")
			/* fmt.Println(header)
			if header {
				req.Header.Set("Content-Type", "application/json")
			} */

			// 发送请求
			resp, err := client.Do(result.Request)
			if err != nil {
				fmt.Println("Error sending request:", err)
			}
			defer resp.Body.Close()

			// 读取响应体
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				fmt.Println("Error reading response body:", err)
			}
			// fmt.Println(string(body))
			decodedString, err := utils.ParseUnicode(string(body))
			if err != nil {
				fmt.Println("Error parsing Unicode:", err)
			}

			lex := lexer.New(decodedString)
			p := parser.New(lex)
			program := p.ParseProgram()
			return utils.ParserSyntaxTrees(program, env)
		},
	},
	/*
		* 打开文件
		file: 必需，文件路径（相对或者绝对路径）
		mode: 可选，文件打开模式
			r	只读。在文件的开头开始。
			r+	读/写。在文件的开头开始。
			w	只写。打开并清空文件的内容；如果文件不存在，则创建新文件。
			w+	读/写。打开并清空文件的内容；如果文件不存在，则创建新文件。
			a	追加。打开并向文件末尾进行写操作，如果文件不存在，则创建新文件。
			a+	读/追加。通过向文件末尾写内容，来保持文件内容。
			x	只写。创建新文件。如果文件已存在，则返回 FALSE 和一个错误。
			x+	读/写。创建新文件。如果文件已存在，则返回 FALSE 和一个错误。
	*/
	"fopen": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			file := args[0]
			fileData, err := os.ReadFile(file.Inspect())
			if err != nil {
				log.Fatal(err)
			}
			return &object.String{Value: string(fileData)}
		},
	},
	/*
		* 写入文件
		file: 必需，文件路径（相对或者绝对路径）
		content: 内容
	*/
	"fwrite": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			filePath := args[0]
			content := args[1]
			// 文件存在，追加内容
			// 打开文件
			file, err := os.OpenFile(filePath.Inspect(), os.O_APPEND|os.O_WRONLY, 0644)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()

			// 将内容追加到文件末尾
			_, err = file.Write([]byte(content.Inspect()))
			if err != nil {
				log.Fatal(err)
			}
			return NULL
		},
	},
	//关闭文件
	"fclose": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			/* file := args[0]
			mode := args[1] */
			return NULL
		},
	},
	/*
		* 重命名文件
		oldName: 原始文件名称
		newName: 新的文件名称
	*/
	"frename": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			oldName := args[0]
			newName := args[1]
			err := os.Rename(oldName.Inspect(), newName.Inspect())
			if err != nil {
				fmt.Printf("重命名文件失败: %s\n", err)
				return &object.Boolean{Value: false}
			}
			return &object.Boolean{Value: true}
		},
	},
	/*
		* 创建文件夹
		dirName: 文件夹名称
	*/
	"mkdir": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			dirName := args[0]
			err := os.Mkdir(dirName.Inspect(), 0755)
			if err != nil {
				fmt.Printf("创建文件夹失败: %s\n", err)
				return &object.Boolean{Value: false}
			}
			return &object.Boolean{Value: true}
		},
	},
	//删除文件夹或文件
	"remove": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			dirName := args[0]

			// 删除文件夹
			err := os.RemoveAll(dirName.Inspect())
			if err != nil {
				fmt.Printf("删除文件夹失败: %s\n", err)
				return &object.Boolean{Value: false}
			}
			return &object.Boolean{Value: true}
		},
	},
	//获取当前工作目录
	"getcwd": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			currentDir, errs := os.Getwd()
			if errs != nil {
				log.Fatal(errs)
			}
			return &object.String{Value: string(currentDir)}
		},
	},
	//获取随机数
	"rand": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {

			min := args[0]
			max := args[1]

			// 设置随机数种子，通常使用当前时间
			rand.Seed(time.Now().UnixNano())
			mins, err := strconv.Atoi(min.Inspect())
			if err != nil {
				fmt.Println("转换错误:", err)
			}
			maxs, err := strconv.Atoi(max.Inspect())
			if err != nil {
				fmt.Println("转换错误:", err)
			}
			randomIntInRange := rand.Intn(maxs-mins) + mins

			return &object.Integer{Value: int64(randomIntInRange)}
		},
	},
	//Base64编码
	"base64_decode": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			decodeString := args[0]
			// 待编码的数据
			data := []byte(decodeString.Inspect())
			// 使用base64.StdEncoding.EncodeToString进行编码
			encodedString := base64.StdEncoding.EncodeToString(data)
			return &object.String{Value: string(encodedString)}
		},
	},
	//Base64解码
	"base64_encode": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			encodedString := args[0]
			// 使用base64.StdEncoding.DecodeString进行解码
			decodedData, err := base64.StdEncoding.DecodeString(encodedString.Inspect())
			if err != nil {
				fmt.Println("Base64 解码错误:", err)
			}
			return &object.String{Value: string(decodedData)}
		},
	},
	//转字符串
	"string": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			switch arg := args[0].(type) {
			case *object.Integer:
				return &object.String{Value: strconv.FormatInt(arg.Value, 10)}
			case *object.Float:
				return &object.String{Value: strconv.FormatFloat(arg.Value, 'f', -1, 64)}
			case *object.String:
				return &object.String{Value: arg.Value}
			case *object.Boolean:
				return &object.String{Value: fmt.Sprintf("%t", arg.Value)}
			case *object.Array:
				return &object.String{Value: arg.Inspect()}
			case *object.Hash:
				return &object.String{Value: arg.Inspect()}
			}
			return NULL
		},
	},
	//转整数
	"int": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			switch arg := args[0].(type) {
			case *object.Integer:
				return &object.Integer{Value: arg.Value}
			case *object.Float:
				return &object.Integer{Value: int64(arg.Value)}
			case *object.String:
				num, err := strconv.Atoi(arg.Inspect())
				if err != nil {
					fmt.Println("转换错误:", err)
				}
				return &object.Integer{Value: int64(num)}

			}
			return NULL
		},
	},
	//转浮点型数字
	"float": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			switch arg := args[0].(type) {
			case *object.Integer:
				// return &object.Float{Value: strconv.FormatInt(arg.Value, 10)}
				return &object.Float{Value: float64(arg.Value)}
			case *object.Float:
				return &object.Float{Value: arg.Value}
			case *object.String:
				num, err := strconv.ParseFloat(arg.Value, 64)
				if err != nil {
					fmt.Println("转换错误:", err)
				}
				return &object.Float{Value: num}
			}
			return NULL
		},
	},
	//字符串截取
	"substr": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			str := args[0].Inspect()
			min := args[1]
			mins, err := strconv.Atoi(min.Inspect())
			if err != nil {
				fmt.Println("转换错误:", err)
			}
			if isParams(args, 2) {
				max, err := strconv.Atoi(args[2].Inspect())
				if err != nil {
					fmt.Println("转换错误:", err)
				}
				substring := str[mins:max]
				return &object.String{Value: substring}
			}
			substring := str[:mins]
			return &object.String{Value: substring}
		},
	},
	//json字符串转json
	"json_decode": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			env := object.NewEnvironment()
			str := args[0].Inspect()
			lex := lexer.New(str)
			p := parser.New(lex)

			program := p.ParseProgram()
			result := utils.ParserSyntaxTrees(program, env)
			return result
		},
	},
	//arr字符串转数组
	"arr_decode": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			str := args[0].Inspect()
			env := object.NewEnvironment()
			lex := lexer.New(str)
			p := parser.New(lex)

			program := p.ParseProgram()
			result := utils.ParserSyntaxTrees(program, env)
			return result
		},
	},
	//字符串转数组
	"split": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			str := args[0].Inspect()
			splitter := " "
			if isParams(args, 1) {
				//分割符
				splitter = args[1].Inspect()
			}
			arr := strings.Split(str, splitter)

			strArray := "let splitArr=["
			for _, value := range arr {
				strArray += "\"" + value + "\","
			}
			strArray += "];"
			strArray = utils.RemoveLastSubstring(strArray, ",")
			env := object.NewEnvironment()
			lex := lexer.New(strArray)
			p := parser.New(lex)

			program := p.ParseProgram()
			result := utils.ParserSyntaxTrees(program, env)
			return result
		},
	},
	//len查看长度
	"len": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			switch arg := args[0].(type) {
			case *object.Integer:
				//将 int64 转换为字符串，10 表示十进制
				numStr := strconv.FormatInt(arg.Value, 10) // 将数字转换为字符串
				length := len(numStr)                      // 获取字符串的长度
				return &object.Integer{Value: int64(length)}
			case *object.Float:
				numStr := strconv.FormatFloat(arg.Value, 'f', -1, 64) // 将浮点数转换为字符串，'f' 表示定点表示法，-1 表示不限制小数位数
				length := len(numStr)                                 // 获取字符串的长度
				return &object.Integer{Value: int64(length)}
			case *object.String:
				length := len(arg.Value) // 获取字符串的长度
				return &object.Integer{Value: int64(length)}
			case *object.Array:
				length := len(arg.Elements) // 获取字符串的长度
				return &object.Integer{Value: int64(length)}
			/* case *object.Hash:
			length := len(arg.Pairs) // 获取字符串的长度
			return &object.Integer{Value: int64(length)} */

			default:
				exception.Evaluator(0, 0, "不支持对\"len\"的论点，得到 %s", args[0].Type())

			}
			return NULL
		},
	},
	//indexof返回字符位置
	"indexof": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			item := args[0].Inspect()
			char := args[1].Inspect()
			if strings.Contains(item, string(char)) {
				// fmt.Printf("字符串 '%s' 包含字符 '%c'\n", str, char)
				return &object.Boolean{Value: true}
			}
			return &object.Boolean{Value: false}
		},
	},
	//获取配置文件中的信息
	"config": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			fileData, err := os.ReadFile("config.cfg")
			if err != nil {
				log.Fatal(err)
			}
			env := object.NewEnvironment()
			lex := lexer.New(string(fileData))
			p := parser.New(lex)

			program := p.ParseProgram()
			result := utils.ParserSyntaxTrees(program, env)
			return result
		},
	},

	//设置文件开机启动
	"setStartupOptions": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			name := args[0].Inspect()
			filePath := args[1].Inspect()
			key, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
			if err != nil {
				fmt.Println("Error opening key:", err)
			}
			defer key.Close()

			err = key.SetStringValue(name, filePath)
			if err != nil {
				fmt.Println("Error setting value:", err)
				return &object.Boolean{Value: false}
			}

			return &object.Boolean{Value: true}
		},
	},
	//取消文件开机启动
	"cancelStartupOptions": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			name := args[0].Inspect()

			key, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
			if err != nil {
				fmt.Println("Error opening key:", err)
			}
			defer key.Close()

			err = key.DeleteValue(name)
			if err != nil {
				log.Fatal(err)
				return &object.Boolean{Value: false}
			}

			return &object.Boolean{Value: true}
		},
	},
	//打开可执行文件
	"openExeFile": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			name := args[0].Inspect()

			cmd := exec.Command(name)
			err := cmd.Run()
			if err != nil {
				log.Fatal(err)
				return &object.Boolean{Value: false}
			}

			return &object.Boolean{Value: true}
		},
	},
	//执行window命令
	"command": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			name := args[0].Inspect()

			cmd := exec.Command(name)
			err := cmd.Run()
			if err != nil {
				log.Fatal(err)
				return &object.Boolean{Value: false}
			}

			return &object.Boolean{Value: true}
		},
	},
	//复制文字到剪切板
	"copyToClipboard": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			name := args[0].Inspect()

			// 复制内容到剪切板
			clipboard.WriteAll(name)

			return &object.Boolean{Value: true}
		},
	},
}

// 判断参数是否存在
func isParams(arr []object.Object, index int) bool {
	for i, _ := range arr {
		if i == index {
			return true
		}
	}
	return false
}
